<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div id="test">尚硅谷IT教育</div>

    <div id="demo">
      <ul>
        <li>test1</li>
        <li>test2</li>
        <li>test3</li>
      </ul>
    </div>

    <!--
1. [].slice.call(lis): 将伪数组转换为真数组
2. node.nodeType: 得到节点类型
3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
6. DocumentFragment: 文档碎片(高效批量更新多个节点)
-->

    <script type="text/javascript">
      /*
        1. [].slice.call(lis): 将伪数组转换为真数组
        2. node.nodeType: 得到节点类型
        3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
        4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
        5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
        6. DocumentFragment: 文档碎片(高效批量更新多个节点)
        */

      // 1. [].slice.call(lis)
      const lis = document.querySelectorAll("li");
      console.log(Array.from(lis)); // ES6
      console.log([].slice.call(lis));
      console.log(Array.prototype.slice.call(lis));

      // 2. node.nodeType
      // 元素节点 1
      // 文本节点 3
      console.log(lis[0].nodeType);

      // 3. Object.defineProperty(obj, propertyName, {})
      const person = {
        firstName: "李",
        lastName: "赔钱",
      };

      // 定义属性的属性（定义属性的元属性）
      Object.defineProperty(person, "fullName", {
        // writable: true, // 是否可写
        enumerable: true, // 是否可枚举、遍历 for in
        configurable: true, // 是否可以重新配置或删除
        get() {
          return this.firstName + " " + this.lastName;
        },
        set(val) {
          const [firstName, lastName] = val.split(" ");
          this.firstName = firstName;
          this.lastName = lastName;
        },
      });

      console.log(person);
      delete person.fullName;

      // 4. Object.keys(obj) 提取对象上所有自身上可枚举属性
      const person1 = {
        firstName: "李",
        lastName: "赔钱",
      };
      person1.__proto__.aaa = 1;

      Object.defineProperty(person1, "bbb", {
        writable: true, // 是否可写
        enumerable: false, // 是否可枚举、遍历 for in
        configurable: true, // 是否可以重新配置或删除
        value: 2,
      });

      // console.log(Object.keys(person1));
      // 遍历对象的方式
      Object.keys(person1).forEach((key) => {
        console.log(key, person1[key]);
      });

      // 5. obj.hasOwnProperty(prop)
      const $$hasOwnProperty = Object.prototype.hasOwnProperty;
      const person2 = {
        firstName: "李",
        lastName: "赔钱",
      };
      person2.__proto__.aaa = 1;
      // console.log(person2);
      for (const key in person2) {
        // if (person2.hasOwnProperty(key)) {
        if ($$hasOwnProperty.call(person2, key)) {
          console.log(key);
        }
      }

      // 6. DocumentFragment

      // 创建文档碎片节点
      const fragment = document.createDocumentFragment();
      // 将DOM添加到文档碎片节点中
      const box = document.getElementById("demo");
      // console.dir(ul);
      fragment.appendChild(box.children[0]);

      // 在文档碎片节点中操作DOM，完成修改...
      const childNodes = fragment.childNodes[0].childNodes;
      [].slice.call(childNodes).forEach((node) => {
        if (node.nodeType === 1) {
          // console.log(node);
          node.textContent = node.textContent + "~~~~";
        }
      });
      // 将操作完成文档碎片节点中的DOM元素添加到页面中生效
      box.appendChild(fragment);
    </script>
  </body>
</html>
